package com.geezdata.cps.cqrs.event.bus.impl;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.geezdata.cps.base.enums.ErrorCode;
import com.geezdata.cps.base.exceptions.MyException;
import com.geezdata.cps.cqrs.event.Event;
import com.geezdata.cps.cqrs.event.annotation.EventPublisher;
import com.geezdata.cps.cqrs.event.bus.EventBus;
import com.geezdata.cps.cqrs.event.enums.EventSource;
import com.geezdata.cps.cqrs.event.publish.Publisher;
import com.google.common.collect.Maps;


public class DefaultEventBus implements EventBus {
    private static Logger logger = LoggerFactory.getLogger(DefaultEventBus.class);

    private Map<EventSource, Publisher> publisherMap = Maps.newHashMap();

    @Override
    public <T> void publish(Event<T> event, EventSource source) {
        Publisher publisher = publisherMap.get(source);

        if (publisher == null) {
        	logger.error("Unknow event type.");
            throw new MyException(ErrorCode.INTERNAL_SERVER_ERROR);
        }

        publisher.publish(event);
    }

    @Override
    public void register(Publisher publisher) {
        if (publisher == null) {
            throw new NullPointerException("Publisher can't be null.");
        }

        EventPublisher eventPublisher = publisher.getClass().getAnnotation(EventPublisher.class);

        if (eventPublisher == null || publisherMap.get(eventPublisher.source()) != null) {
            String msg = "Publisher register fail. {} is not a valid publisher";
            logger.error(msg, publisher.getClass().getSimpleName());
            throw new MyException(ErrorCode.INTERNAL_SERVER_ERROR);
        }

        publisherMap.put(eventPublisher.source(), publisher);
    }
}
